home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
graphics
/
qrt.lzh
/
RAY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-16
|
19KB
|
771 lines
/************************************************************
ray trace module
************************************************************/
#include <math.h>
#include "qrt.h"
/* #define RAYDEBUG 1 */
OBJ_PTR new_line(), new_obj();
/**********************************************************
Diffuse color module. Also compute specular reflections
here for efficiency sake - only one lamp eneumerator
needed that way.
**********************************************************/
DiffColor(color,cinfo,norm,loc,oline)
SVECT_PTR color;
VECT_PTR norm,loc;
CINFO_PTR cinfo;
OBJ_PTR oline;
{
OBJ_PTR lamp, line, CurrObj, Ray_Hit();
float t;
register float dist, t1,t2;
VECTOR refl, atten;
line=new_line();
VectEQ(&(line->loc),loc);
lamp=THEWORLD.lamps;
while (lamp!=NULL) {
# ifdef ROBUST
if (lamp->type!=LAMP) Error(INTERNAL_ERROR,601);
# endif
/* find dir to lamp */
VecSubtract(&(line->vect1),&(lamp->loc),loc);
CurrObj=NULL;
atten.x = atten.y = atten.z = 1.00;
if (def.shadow==TRUE) {
/* set light attenuation factor */
CurrObj=Ray_Hit(THEWORLD.stack,line,&t,TRUE,TRUE,&atten);
THEWORLD.to_lamp++;
}
if (CurrObj==NULL) { /* hit nothing ? */
dist = DotProd((line->vect1),(line->vect1));
Normalize(&(line->vect1));
if (cinfo->diff.r>0 || cinfo->diff.g>0 || cinfo->diff.b>0) {
t1 = DotProd((*norm),(line->vect1));
if (t1>0) {
t2 = lamp->vect1.y*t1/sqrt(dist);
color->r+=(short)((lamp->cinfo.amb.r) * atten.x *
t2*(cinfo->diff.r)/CNUM);
color->g+=(short)((lamp->cinfo.amb.g) * atten.y *
t2*(cinfo->diff.g)/CNUM);
color->b+=(short)((lamp->cinfo.amb.b) * atten.z *
t2*(cinfo->diff.b)/CNUM);
}
}
if (cinfo->sreflect>0) { /* specular */
line->vect1.x = -line->vect1.x; /* reverse line */
line->vect1.y = -line->vect1.y;
line->vect1.z = -line->vect1.z;
Reflect(&refl,&(line->vect1),norm);
t1 = -DotProd(refl,(oline->vect1));
if (t1>0) {
t2 = pow(t1,cinfo->sreflect)* /* this is slow !! */
lamp->vect1.y/sqrt(dist);
t2 *= (float)cinfo->reflect/(float)CNUM;
color->r+=(short)(t2 * atten.x * (lamp->cinfo.amb.r));
color->g+=(short)(t2 * atten.y * (lamp->cinfo.amb.g));
color->b+=(short)(t2 * atten.z * (lamp->cinfo.amb.b));
}
}
}
lamp=lamp->nextobj;
}
# ifdef RAYDEBUG
printf("DIFFCOLOR: r=%d, g=%d, b=%d\n",
color->r, color->g, color->b);
# endif
free(line);
}
/**********************************************************
Ambient color module
Really simple - just add the color, no questions asked.
**********************************************************/
AmbColor(color, cinfo, norm, loc)
SVECT_PTR color;
VECT_PTR norm, loc;
CINFO_PTR cinfo;
{
color->r+=(short)((int)cinfo->amb.r*(int)cinfo->diff.r/CNUM);
color->g+=(short)((int)cinfo->amb.g*(int)cinfo->diff.g/CNUM);
color->b+=(short)((int)cinfo->amb.b*(int)cinfo->diff.b/CNUM);
# ifdef RAYDEBUG
printf("AMBCOLOR: added r=%d, g=%d, b=%d\n",
cinfo->amb.r,cinfo->amb.g,cinfo->amb.b);
# endif
}
/**********************************************************
Transmitted color module
This is hairy and slow - bends ray around normal vector
by ratio of indicies of refraction. line->flag=TRUE
if we are inside a piece of glass - this means glass must
have a simple structure.
10 Aug 88 - Fixed TransColor so that it works. The
original algorithm came from a book, and I had some
problems getting it to work. This one came from my head,
and seems to work ok.
11 Aug 88 - Added density effects (light is reduced
more by thicker glass).
**********************************************************/
/* #define TESTTRANS TRUE */
TransColor(color,cinfo,norm,loc,line,inmult)
SVECT_PTR color;
VECT_PTR norm,loc;
OBJ_PTR line;
CINFO_PTR cinfo;
float inmult;
{
OBJ_STRUCT newline;
SVECTOR col1;
VECTOR toadd, negvect1, distance;
float index2, multiplier, side1;
int maxtrans;
/* these vars are used to keep track of the distance
traveled through the glass so we can attenuate the
light accordingly. */
static VECTOR prevpos;
VECTOR displacement;
SVECTOR attenuation;
float glassdist;
# ifdef TRANSDEBUG
printf("TRANSCOLOR:\n");
# endif
# ifdef RAYDEBUG
printf("TRANSCOLOR:\n");
# endif
if ((cinfo->trans.r < def.ithreshold) &&
(cinfo->trans.g < def.ithreshold) &&
(cinfo->trans.b < def.ithreshold)) return;
# ifdef ROBUST
if (line->type!=LINE) Error(INTERNAL_ERROR,602);
if ((THEWORLD.globindex == 0) ||
(cinfo->index == 0))
Error(ZERO_INDEX,603);
# endif
if (line->flag) {
/* inside an object going out ? */
index2 = cinfo->index/THEWORLD.globindex;
/* find offset from prev position */
VecSubtract(&displacement,loc,&prevpos);
/* measure distance */
glassdist = sqrt(DotProd(displacement,displacement));
} else {
/* outside an object going in ? */
index2 = THEWORLD.globindex/cinfo->index;
/* remember this position */
VectEQ(&prevpos,loc);
}
/* doesn't currently use new_line() call */
newline.type = LINE;
newline.child = newline.nextobj = NULL;
/* this ray starts from where we hit glass */
VectEQ(&(newline.loc),loc);
VectEqZero(&toadd);
VectNegate(&negvect1,&(line->vect1));
side1 = DotProd((*norm),negvect1);
VectAddMult(&toadd,-side1,norm,(float)1,&negvect1);
VectScale(&toadd,(1-index2));
VectorAdd(&(newline.vect1),&(line->vect1),&toadd);
Normalize(&(newline.vect1));
maxtrans = MAX(MAX(cinfo->trans.r,cinfo->trans.g),
cinfo->trans.b);
/* if we were inside, now we're out */
newline.flag = !(line->flag);
# ifdef TESTTRANS
if (line->flag) printf("line TRUE\n");
if (newline.flag) printf("newline TRUE\n");
printf("Trans = %d %d %d\n",cinfo->trans.r,
cinfo->trans.g,
cinfo->trans.b);
printf("index2 = %f\n",index2);
printf("side1 = %f\n",side1);
printf("Dot(toadd,norm) = %f\n",
DotProd(toadd,(*norm)));
printf("Dot(norm,negvect1) = %f\n",
DotProd((*norm),negvect1));
printf("Dot(-norm,newvect) = %f\n",
-DotProd((*norm),newline.vect1));
printf("inmult, maxtrans = %f %d\n",inmult,maxtrans);
# endif
multiplier = inmult * (float)maxtrans/(float)CNUM;
Ray_Trace(&newline,&col1,multiplier);
THEWORLD.refl_trans++;
# ifdef TESTTRANS
printf("Col1 = %d %d %d\n",col1.r,col1.g,col1.b);
# endif
color->r += col1.r;
color->g += col1.g;
color->b += col1.b;
if (line->flag) { /* density effects? */
/* density uses x,y,z not r,g,b cuz its a floating
point vector. */
attenuation.r = (int)(cinfo->density.x * glassdist *
(float)(color->r));
attenuation.g = (int)(cinfo->density.y * glassdist *
(float)(color->g));
attenuation.b = (int)(cinfo->density.z * glassdist *
(float)(color->b));
/* don't remove more than original intensity! */
color->r -= MIN(attenuation.r,color->r);
color->g -= MIN(attenuation.g,color->g);
color->b -= MIN(attenuation.b,color->b);
}
}
/**********************************************************
Reflective color module
Bounce ray off object and recursively ray trace.
**********************************************************/
ReflectColor(color,cinfo,norm,loc,line,inmult)
SVECT_PTR color;
VECT_PTR norm,loc;
OBJ_PTR line;
CINFO_PTR cinfo;
float inmult;
{
SVECTOR col1;
OBJ_STRUCT newline;
float multiplier;
int maxmirror;
# ifdef ROBUST
if (line->type!=LINE) Error(INTERNAL_